#include "config.h"

#include <sys/types.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <dirent.h>
#include <unistd.h>

#define DBG_SUBSYS S_LIBCONTROL

#include "net_global.h"
#include "core.h"
#include "volume_ctl.h"
#include "stor_rpc.h"

#include "controller_internal.h"
#include "dbg.h"


static void __volume_remote_io_read(void *arg) {
        int ret;
        remote_io_read_ctx_t *ctx = arg;

        if (net_islocal(&ctx->nid)) {
                ret = volume_ctl_read(ctx->io, ctx->buf, 0);
                if (unlikely(ret))
                        GOTO(err_ret, ret);
        } else {
                ret = stor_rpc_read(&ctx->nid, ctx->io, ctx->buf);
                if (unlikely(ret))
                        GOTO(err_ret, ret);
        }

        ctx->retval = 0;
        return;
err_ret:
        ctx->retval = ret;
        return;
}

int volume_remote_io_read(const nid_t *nid, const io_t *io, buffer_t *buf) {
        int ret;
        remote_io_read_ctx_t ctx;

        DINFO("remote io: nid %d chkid %s off %llu size %u\n", nid->id,
              id2str(&io->id), (LLU)io->offset, io->size);

        ANALYSIS_BEGIN(0);

        ctx.nid = *nid;
        ctx.io = io;
        ctx.buf = buf;
        ctx.retval = 0;

        //YASSERT(core_self() && core_self()->hash == core_hash(snapid));

        ret = core_request0(core_hash(&io->id), __volume_remote_io_read,
                            &ctx, "volume_remote_io");
        if (unlikely(ret)) {
                if (ret == ESTALE) {
                        ret = EAGAIN;
                        GOTO(err_ret, ret);
                } else
                        GOTO(err_ret, ret);
        }

        ret = ctx.retval;
        if (unlikely(ret))
                GOTO(err_ret, ret);

        ANALYSIS_END(0, IO_WARN, NULL);

        return 0;
err_ret:
        return ret;
}
